/****h* scdbxml/context.c
 *  NAME
 *    context.c
 *  DESCRIPTION
 *********/
#include "context.h"

/*
 * initialise writer context
 */
/****f* context.c/userWriterCtxtInitialise
 *  NAME
 *    userWriterCtxtInitialise
 *  SYNOPSIS
 *    userWriterCtxt userWriterCtxtInitialise(char *filename)
 *  ARGUMENTS
 *  RETURN TYPE
 *  AUTHOR
 *  SOURCE
*/
userWriterCtxt userWriterCtxtInitialise(char *filename)
	/*{{{*/
{
	 char *error;
	 const char *leftover;
	 userWriterCtxt ctxt = NULL;
	 
	 while (1) 
		 {
				/*
				 * initialise context
				 */
				ctxt = (userWriterCtxt) malloc(sizeof(struct _userwriterctxt));
				if (NULL == ctxt) 
					{
						 break;
					}
				
				/*
				 * no error so far
				 */
				ctxt->error = SCDBXML_OK;
				
				/*
				 * open database named by filename
				 * and set some pragmas for speed
				 * and start a transaction
				 */
				if (SQLITE_OK != sqlite3_open(filename, &ctxt->db)) 
					{
						 userWriterCtxtError(ctxt, SCDBXML_OPEN, __LINE__, __FILE__);
						 break;
					}
	 
				if (SQLITE_OK != sqlite3_exec(ctxt->db, "PRAGMA synchronous = OFF", NULL, NULL, &error) ||
						SQLITE_OK != sqlite3_exec(ctxt->db, "PRAGMA count_changes = 0", NULL, NULL, &error) ||
						SQLITE_OK != sqlite3_exec(ctxt->db, "PRAGMA temp_store = MEMORY", NULL, NULL, &error) ||
						SQLITE_OK != sqlite3_exec(ctxt->db, "BEGIN TRANSACTION", NULL, NULL, &error)) 
					{
						 userWriterCtxtError(ctxt, SCDBXML_EXEC, __LINE__, __FILE__);
						 break;
					}
				
				/*
				 * precompile statements for inserting nodes
				 */
				
				/*
				 * insert document (source name)
				 */
				if (SQLITE_OK != sqlite3_prepare(ctxt->db, INSERT_DOC, -1, 
																				 &ctxt->insertDoc, &leftover) ||
						/*
						 * insert node (x, y, depth, document id and type)
						 */
						SQLITE_OK != sqlite3_prepare(ctxt->db, INSERT_NOD, -1, 
																				 &ctxt->insertNod, &leftover) ||
						/*
						 * insert element (node id, name)
						 */
						SQLITE_OK != sqlite3_prepare(ctxt->db, INSERT_ELM, -1, 
																				 &ctxt->insertElm, &leftover) ||
						/*
						 * insert attribute (node id, name, value)
						 */
						SQLITE_OK != sqlite3_prepare(ctxt->db, INSERT_ATT, -1, 
																				 &ctxt->insertAtt, &leftover) ||
						/*
						 * insert text (node id, value)
						 */
						SQLITE_OK != sqlite3_prepare(ctxt->db, INSERT_TXT, -1, 
																				 &ctxt->insertTxt, &leftover) ||
						/*
						 * insert element namespace (node id, uri, prefix)
						 */
						SQLITE_OK != sqlite3_prepare(ctxt->db, INSERT_ENS, -1, 
																				 &ctxt->insertEns, &leftover) ||
						/*
						 * insert attribute namespace (node id, uri, prefix)
						 */
						SQLITE_OK != sqlite3_prepare(ctxt->db, INSERT_ANS, -1, 
																				 &ctxt->insertAns, &leftover) ||
						/*
						 * insert processing instruction (node id, name, value)
						 */
						SQLITE_OK != sqlite3_prepare(ctxt->db, INSERT_PI, -1,
																				 &ctxt->insertPI, &leftover) ||
						/*
						 * insert comment (node id, value)
						 */
						SQLITE_OK != sqlite3_prepare(ctxt->db, INSERT_COM, -1,
																				 &ctxt->insertCom, &leftover)) 
					{
						 userWriterCtxtError(ctxt, SCDBXML_PREPARE, __LINE__, __FILE__);
						 break;
					}
						
				/*
				 * no nodes at the moment
				 */
				ctxt->node_count = 0;
				ctxt->max_nodes = MAX_NODES;
				
				ctxt->nodes = (node) malloc(sizeof(struct _node) * ctxt->max_nodes);
				if (NULL == ctxt->nodes) 
					{
						 userWriterCtxtError(ctxt, SCDBXML_MALLOC, __LINE__, __FILE__);
						 break;
					}

				/*
				 * no entities at the moment
				 */
				ctxt->entities = NULL;
				
				break;
		 }
	 
	 return ctxt;
}
/*}}}*/

/*
 * initialise reader context
 */
/************ userWriterCtxtInitialise */
/****f* context.c/userReaderCtxtInitialise
 *  NAME
 *    userReaderCtxtInitialise
 *  SYNOPSIS
 *    userReaderCtxt userReaderCtxtInitialise(char *filename)
 *  ARGUMENTS
 *  RETURN TYPE
 *  AUTHOR
 *  SOURCE
*/
userReaderCtxt userReaderCtxtInitialise(char *filename)
	/*{{{*/
{
	 const char *leftover;
	 userReaderCtxt ctxt;
	 
	 while (1) 
		 {
				/*
				 * initialise context
				 */
				ctxt = (userReaderCtxt) malloc(sizeof(struct _userreaderctxt));
				if (NULL == ctxt) 
					{
						 break;
					}

				/*
				 * open database named by filename
				 */
				if (SQLITE_OK != sqlite3_open(filename, &ctxt->db)) 
					{
						 userReaderCtxtError(ctxt, SCDBXML_OPEN, __LINE__, __FILE__);
						 break;
					}
				
				/*
				 * precompile statements for selecting nodes
				 */
				
				/*
				 * get document SQL
				 */
				if (SQLITE_OK != sqlite3_prepare(ctxt->db, 
																				 "SELECT * FROM ("
																				 "SELECT nod.*, elm.nname, NULL, ens.uri, ens.prefix "
																				 "FROM nod "
																				 "INNER JOIN elm "
																				 "ON nod.nod_id = elm.nod_id "
																				 "LEFT JOIN ens "
																				 "ON nod.nod_id = ens.nod_id "
																				 "WHERE nod.doc_id = ? "
																				 "UNION "
																				 "SELECT nod.*, att.nname, att.nval, ans.uri, ans.prefix "
																				 "FROM nod "
																				 "INNER JOIN att "
																				 "ON nod.nod_id = att.nod_id "
																				 "LEFT JOIN ans "
																				 "ON nod.nod_id = ans.nod_id "
																				 "WHERE nod.doc_id = ? "
																				 "UNION "
																				 "SELECT nod.*, NULL, txt.nval, NULL, NULL "
																				 "FROM nod "
																				 "INNER JOIN txt "
																				 "ON nod.nod_id = txt.nod_id "
																				 "WHERE nod.doc_id = ? "
																				 "UNION SELECT nod.*, NULL, com.nval, NULL, NULL "
																				 "FROM nod "
																				 "INNER JOIN com "
																				 "ON nod.nod_id = com.nod_id "
																				 "WHERE nod.doc_id = ? "
																				 "UNION "
																				 "SELECT nod.*, pi.nname, pi.nval, NULL, NULL "
																				 "FROM nod "
																				 "INNER JOIN pi "
																				 "ON nod.nod_id = pi.nod_id "
																				 "WHERE nod.doc_id = ?) "
																				 "ORDER BY x",
																				 -1, &ctxt->getDocument, &leftover)) 
					{
						 userReaderCtxtError(ctxt, SCDBXML_PREPARE, __LINE__, __FILE__);
						 break;
					}
			
				/*
				 * no nodes at the moment
				 * initialise array for max nodes
				 */
				ctxt->node_count = 0;
				ctxt->max_nodes = MAX_NODES;
				ctxt->nodes = (node) malloc(sizeof(struct _node) * ctxt->max_nodes);
				if (NULL == ctxt->nodes) 
					{
						 userReaderCtxtError(ctxt, SCDBXML_MALLOC, __LINE__, __FILE__);
						 break;
					}
				
				/*
				 * initialise xml document
				 */
				ctxt->doc = xmlNewDoc((const xmlChar *) "1.0");
				
				break;
		 }

	 return ctxt;
}
/*}}}*/

/*
 * finished with writer context
 */
/************ userReaderCtxtInitialise */
/****f* context.c/userWriterCtxtFinish
 *  NAME
 *    userWriterCtxtFinish
 *  SYNOPSIS
 *    void userWriterCtxtFinish(userWriterCtxt ctxt)
 *  ARGUMENTS
 *  RETURN TYPE
 *  AUTHOR
 *  SOURCE
*/
void userWriterCtxtFinish(userWriterCtxt ctxt)
	/*{{{*/
{
	 char *error = NULL;
	 xmlEntityPtr e = NULL;
	 
	 while (1) 
		 {
				/*
				 * commit transaction
				 */
				if (SQLITE_OK != sqlite3_exec(ctxt->db, "COMMIT TRANSACTION", NULL, NULL, &error)) 
					{
						 userWriterCtxtError(ctxt, SCDBXML_COMMIT, __LINE__, __FILE__);
						 break;
					}
				
				/*
				 * finalise statements
				 */
				if (SQLITE_OK != sqlite3_finalize(ctxt->insertDoc) ||
						SQLITE_OK != sqlite3_finalize(ctxt->insertNod) ||
						SQLITE_OK != sqlite3_finalize(ctxt->insertElm) ||
						SQLITE_OK != sqlite3_finalize(ctxt->insertAtt) ||
						SQLITE_OK != sqlite3_finalize(ctxt->insertTxt) ||
						SQLITE_OK != sqlite3_finalize(ctxt->insertEns) ||
						SQLITE_OK != sqlite3_finalize(ctxt->insertAns) ||
						SQLITE_OK != sqlite3_finalize(ctxt->insertPI) ||
						SQLITE_OK != sqlite3_finalize(ctxt->insertCom)) 
					{
						 userWriterCtxtError(ctxt, SCDBXML_FINALIZE, __LINE__, __FILE__);
						 break;
					}
				
				/*
				 * commit and close db
				 */
				if (SQLITE_OK != sqlite3_close(ctxt->db)) 
					{
						 userWriterCtxtError(ctxt, SCDBXML_CLOSE, __LINE__, __FILE__);
						 break;
						 
					}

				/*
				 * free nodes
				 * and entities
				 */
				free(ctxt->nodes);
				
				while (NULL != ctxt->entities)
					{
						 e = ctxt->entities;
						 if (NULL != e->name) 
							 {
									free((void *) e->name);
							 }
						 if (NULL != e->content) 
							 {
									free((void *) e->content);
							 }
						 if (NULL != e->SystemID) 
							 {
									free((void *) e->SystemID);
							 }
						 if (NULL != e->ExternalID) 
							 {
									free((void *) e->ExternalID);
							 }
						 if (NULL != e->URI) 
							 {
									free((void *) e->URI);
							 }
						 if (NULL != e->orig) 
							 {
									free((void *) e->orig);
							 }
						 ctxt->entities = ctxt->entities->nexte;
						 free(e);
					}
				
				break;
		 }
}
/*}}}*/

/*
 * remember the XML file to be read
 */
/************ userWriterCtxtFinish */
/****f* context.c/userWriterCtxtSetFile
 *  NAME
 *    userWriterCtxtSetFile
 *  SYNOPSIS
 *    void userWriterCtxtSetFile(userWriterCtxt context, char *xmlfile)
 *  ARGUMENTS
 *  RETURN TYPE
 *  AUTHOR
 *  SOURCE
*/
void userWriterCtxtSetFile(userWriterCtxt context, char *xmlfile)
	/*{{{*/
{
	 context->xmlfile = xmlfile;
}
/*}}}*/

/*
 * insert document
 */
/************ userWriterCtxtSetFile */
/****f* context.c/userWriterCtxtInsertDoc
 *  NAME
 *    userWriterCtxtInsertDoc
 *  SYNOPSIS
 *    void userWriterCtxtInsertDoc(userWriterCtxt ctxt)
 *  ARGUMENTS
 *  RETURN TYPE
 *  AUTHOR
 *  SOURCE
*/
void userWriterCtxtInsertDoc(userWriterCtxt ctxt)
	/*{{{*/
{
	 while (1) 
		 {
				/*
				 * insert document
				 */
				if (SQLITE_OK != sqlite3_bind_text(ctxt->insertDoc,
																					 1,
																					 (const char*) ctxt->xmlfile,
																					 strlen(ctxt->xmlfile),
																					 NULL)) 
					{
						 userWriterCtxtError(ctxt, SCDBXML_BIND, __LINE__, __FILE__);
						 break;
					}
				
				if (SQLITE_DONE != sqlite3_step(ctxt->insertDoc)) 
					{
						 userWriterCtxtError(ctxt, SCDBXML_STEP, __LINE__, __FILE__);
						 break;
					}
				
				if (SQLITE_OK != sqlite3_reset(ctxt->insertDoc)) 
					{
						 userWriterCtxtError(ctxt, SCDBXML_RESET, __LINE__, __FILE__);
						 break;
					}
				
				/*
				 * get id of insert
				 */
				ctxt->doc_id = sqlite3_last_insert_rowid(ctxt->db);
				
				break;
		 }
}
/*}}}*/

/*
 * insert nodes in array
 */
/************ userWriterCtxtInsertDoc */
/****f* context.c/userWriterCtxtInsertNodes
 *  NAME
 *    userWriterCtxtInsertNodes
 *  SYNOPSIS
 *    void userWriterCtxtInsertNodes(userWriterCtxt ctxt)
 *  ARGUMENTS
 *  RETURN TYPE
 *  AUTHOR
 *  SOURCE
*/
void userWriterCtxtInsertNodes(userWriterCtxt ctxt)
	/*{{{*/
{
	 int i;
	 struct _node n;

	 /*
		* loop over nodes in array
		*/
	 for (i = 0; i < ctxt->node_count; ++ i)
		 {
				/*
				 * get node into convrnience variable
				 */
				n = ((userWriterCtxt) ctxt)->nodes[i];
				
				/*
				 * insert node
				 */
				if (SQLITE_OK != sqlite3_bind_int(ctxt->insertNod, 1, n.x) ||
						SQLITE_OK != sqlite3_bind_int(ctxt->insertNod, 2, n.y) ||
						SQLITE_OK != sqlite3_bind_int(ctxt->insertNod, 3, ctxt->doc_id) ||
						SQLITE_OK != sqlite3_bind_int(ctxt->insertNod, 4, n.depth) ||
						SQLITE_OK != sqlite3_bind_int(ctxt->insertNod, 5, n.type)) 
					{
						 userWriterCtxtError(ctxt, SCDBXML_BIND, __LINE__, __FILE__);
						 break;
					}
				
				if (SQLITE_DONE != sqlite3_step(ctxt->insertNod)) 
					{
						 userWriterCtxtError(ctxt, SCDBXML_STEP, __LINE__, __FILE__);
						 break;
					}
				
				if (SQLITE_OK != sqlite3_reset(ctxt->insertNod)) 
					{
						 userWriterCtxtError(ctxt, SCDBXML_RESET, __LINE__, __FILE__);
						 break;
					}
				
				/*
				 * get id of inserted node
				 */
				n.nod_id = sqlite3_last_insert_rowid(ctxt->db);
				n.doc_id = ctxt->doc_id;

				/*
				 * insert element/attribute/text etc.
				 */
				switch (n.type)
					{
					 case XML_ELEMENT_NODE:
							 {
									if (SQLITE_OK != sqlite3_bind_int(ctxt->insertElm, 1, n.nod_id) ||
											SQLITE_OK != sqlite3_bind_text(ctxt->insertElm, 
																										 2,
																										 (char *) n.name,
																										 n.name_len,
																										 SQLITE_TRANSIENT)) 
										{
											 userWriterCtxtError(ctxt, SCDBXML_BIND, __LINE__, __FILE__);
											 break;
										}

									if (SQLITE_DONE != sqlite3_step(ctxt->insertElm)) 
										{
											 userWriterCtxtError(ctxt, SCDBXML_STEP, __LINE__, __FILE__);
											 break;
										}
									
									if (SQLITE_OK != sqlite3_reset(ctxt->insertElm)) 
										{
											 userWriterCtxtError(ctxt, SCDBXML_RESET, __LINE__, __FILE__);
											 break;
										}

									/*
									 * add namespace for element if needed
									 */
									if (0 != n.uri_len)
										{
											 if (SQLITE_OK != sqlite3_bind_int(ctxt->insertEns, 1, n.nod_id) ||
													 SQLITE_OK != sqlite3_bind_text(ctxt->insertEns, 
																													2,
																													(char *) n.uri,
																													n.uri_len,
																													SQLITE_TRANSIENT) ||
													 SQLITE_OK != sqlite3_bind_text(ctxt->insertEns, 
																													3,
																													(char *) n.prefix,
																													n.prefix_len,
																													SQLITE_TRANSIENT))
 
												 {
														userWriterCtxtError(ctxt, SCDBXML_BIND, __LINE__, __FILE__);
														break;
												 }

											 if (SQLITE_DONE != sqlite3_step(ctxt->insertEns)) 
												 {
														userWriterCtxtError(ctxt, SCDBXML_STEP, __LINE__, __FILE__);
														break;
												 }
											 
											 if (SQLITE_OK != sqlite3_reset(ctxt->insertEns)) 
												 {
														userWriterCtxtError(ctxt, SCDBXML_RESET, __LINE__, __FILE__);
														break;
												 }
										}
									
									//DBG(fprintf(stderr, "element %s\n", n.name));
									break;
							 }
					 case XML_TEXT_NODE:
							 {
									if (SQLITE_OK != sqlite3_bind_int(ctxt->insertTxt, 1, n.nod_id) ||
											SQLITE_OK != sqlite3_bind_text(ctxt->insertTxt, 
																										 2,
																										 (char *) n.value,
																										 n.value_len,
																										 SQLITE_TRANSIENT)) 
										{
											 userWriterCtxtError(ctxt, SCDBXML_BIND, __LINE__, __FILE__);
											 break;
										}

									if (SQLITE_DONE != sqlite3_step(ctxt->insertTxt)) 
										{
											 userWriterCtxtError(ctxt, SCDBXML_STEP, __LINE__, __FILE__);
											 break;
										}
									
									if (SQLITE_OK != sqlite3_reset(ctxt->insertTxt)) 
										{
											 userWriterCtxtError(ctxt, SCDBXML_RESET, __LINE__, __FILE__);
											 break;
										}
									
									//DBG(fprintf(stderr, "text %d\n", n.name_len));
									break;
							 }
					 case XML_ATTRIBUTE_NODE:
							 {
									if (SQLITE_OK != sqlite3_bind_int(ctxt->insertAtt, 1, n.nod_id) ||
											SQLITE_OK != sqlite3_bind_text(ctxt->insertAtt, 
																										 2,
																										 (char *) n.name,
																										 n.name_len,
																										 SQLITE_TRANSIENT) ||
											SQLITE_OK != sqlite3_bind_text(ctxt->insertAtt, 
																										 3,
																										 (char *) n.value,
																										 n.value_len,
																										 SQLITE_TRANSIENT)) 
										{
											 userWriterCtxtError(ctxt, SCDBXML_BIND, __LINE__, __FILE__);
											 break;
										}

									if (SQLITE_DONE != sqlite3_step(ctxt->insertAtt)) 
										{
											 userWriterCtxtError(ctxt, SCDBXML_STEP, __LINE__, __FILE__);
											 break;
										}
									
									if (SQLITE_OK != sqlite3_reset(ctxt->insertAtt)) 
										{
											 userWriterCtxtError(ctxt, SCDBXML_RESET, __LINE__, __FILE__);
											 break;
										}

									/*
									 * add namespace for attribute if needed
									 */
									if (0 != n.uri_len)
										{
											 if (SQLITE_OK != sqlite3_bind_int(ctxt->insertAns, 1, n.nod_id) ||
													 SQLITE_OK != sqlite3_bind_text(ctxt->insertAns, 
																													2,
																													(char *) n.uri,
																													n.uri_len,
																													SQLITE_TRANSIENT) ||
													 SQLITE_OK != sqlite3_bind_text(ctxt->insertAns, 
																													3,
																													(char *) n.prefix,
																													n.prefix_len,
																													SQLITE_TRANSIENT)) 
												 {
														userWriterCtxtError(ctxt, SCDBXML_BIND, __LINE__, __FILE__);
														break;
												 }

											 if (SQLITE_DONE != sqlite3_step(ctxt->insertAns)) 
												 {
														userWriterCtxtError(ctxt, SCDBXML_STEP, __LINE__, __FILE__);
														break;
												 }
											 
											 if (SQLITE_OK != sqlite3_reset(ctxt->insertAns)) 
												 {
														userWriterCtxtError(ctxt, SCDBXML_RESET, __LINE__, __FILE__);
														break;
												 }
										}
									
									//DBG(fprintf(stderr, "attribute %s (%s)\n", n.name, n.value));
									break;
							 }
					 case XML_PI_NODE:
							 {
									if (SQLITE_OK != sqlite3_bind_int(ctxt->insertPI, 1, n.nod_id) ||
											SQLITE_OK != sqlite3_bind_text(ctxt->insertPI,
																										 2,
																										 (char *) n.name,
																										 n.name_len,
																										 SQLITE_TRANSIENT) ||
											SQLITE_OK != sqlite3_bind_text(ctxt->insertPI,
																										 3,
																										 (char *) n.value,
																										 n.value_len,
																										 SQLITE_TRANSIENT)) 
										{
											 userWriterCtxtError(ctxt, SCDBXML_BIND, __LINE__, __FILE__);
											 break;
										}
									
									if (SQLITE_DONE != sqlite3_step(ctxt->insertPI)) 
										{
											 userWriterCtxtError(ctxt, SCDBXML_STEP, __LINE__, __FILE__);
											 break;
										}
									
									if (SQLITE_OK != sqlite3_reset(ctxt->insertPI)) 
										{
											 userWriterCtxtError(ctxt, SCDBXML_RESET, __LINE__, __FILE__);
											 break;
										}
									
									//DBG(fprintf(stderr, "PI %s\n", n.name));
									break;
							 }
					 case XML_COMMENT_NODE:
							 {
									if (SQLITE_OK != sqlite3_bind_int(ctxt->insertCom, 1, n.nod_id) ||
											SQLITE_OK != sqlite3_bind_text(ctxt->insertCom, 
																										 2,
																										 (char *) n.value,
																										 n.value_len,
																										 SQLITE_TRANSIENT)) 
										{
											 userWriterCtxtError(ctxt, SCDBXML_BIND, __LINE__, __FILE__);
											 break;
										}

									if (SQLITE_DONE != sqlite3_step(ctxt->insertCom)) 
										{
											 userWriterCtxtError(ctxt, SCDBXML_STEP, __LINE__, __FILE__);
											 break;
										}
									
									if (SQLITE_OK != sqlite3_reset(ctxt->insertCom)) 
										{
											 userWriterCtxtError(ctxt, SCDBXML_RESET, __LINE__, __FILE__);
											 break;
										}
									
									//DBG(fprintf(stderr, "comment %s\n", n.value));
									break;
							 }

						 /*
							* TODO entities etc.
							*/
					 default:
						 break;
					}
				
				if (SCDBXML_OK != ctxt->error) 
					{
						 break;
					}

				/*
				 * free node
				 */
				if (0 != n.uri_len)
					{
						 free(n.uri);
						 n.uri = NULL;
					}
				if (0 != n.prefix_len)
					{
						 free(n.prefix);
						 n.prefix = NULL;
					}
				if (0 != n.name_len)
					{
						 free(n.name);
						 n.name = NULL;
					}
				if (0 != n.value_len)
					{
						 free(n.value);
						 n.value = NULL;
					}
		 }

	 ctxt->node_count = 0;
}
/*}}}*/

/*
 * remember an error
 */
/************ userWriterCtxtInsertNodes */
/****f* context.c/userWriterCtxtError
 *  NAME
 *    userWriterCtxtError
 *  SYNOPSIS
 *    void userWriterCtxtError(userWriterCtxt ctxt, 
 *  ARGUMENTS
 *  RETURN TYPE
 *  AUTHOR
 *  SOURCE
*/
void userWriterCtxtError(userWriterCtxt ctxt, 
												 ctxtError code, 
												 int line, 
												 char* file) 
	/*{{{*/
{
	 ctxt->error = code;
	 ctxt->line = line;
	 ctxt->file = file;
}
/*}}}*/

/************ userWriterCtxtError */
/****f* context.c/userReaderCtxtError
 *  NAME
 *    userReaderCtxtError
 *  SYNOPSIS
 *    void userReaderCtxtError(userReaderCtxt ctxt, 
 *  ARGUMENTS
 *  RETURN TYPE
 *  AUTHOR
 *  SOURCE
*/
void userReaderCtxtError(userReaderCtxt ctxt, 
												 ctxtError code, 
												 int line, 
												 char* file) 
	/*{{{*/
{
	 ctxt->error = code;
	 ctxt->line = line;
	 ctxt->file = file;
}
/*}}}*/
/************ userReaderCtxtError */
